package com.example.kotlindemo.demo

/**
 * Author 87231
 * 2022/8/16 22:11
 *
 * Unit6
 * describe：继承
 * 1.Kotlin中的所有的类都是继承Any类，它是所有类的超类。
 *  构造函数(有主构造函、没有主构造函数)
 * 2.重写：重写的方法名重名的情况下，使用super关键字来区分
 * 3.属性重写：两种方式
 *
 **/
class Unit6 : Any() {
    //    下面的三个类都是继承于Any类中
    override fun equals(other: Any?): Boolean {
        return super.equals(other)
    }

    override fun hashCode(): Int {
        return super.hashCode()
    }

    override fun toString(): String {
        return super.toString()
    }

    /**
     * 一、构造函数
     *  1.当子类有主构造该函数时，基类必须在子类的主构造函数中初始化
     *  2.当子类没有主构造函数时，必须在每一个二级的构造函数中使用super关键字初始化基类
     */
    open class A(name: String, age: Int) { //父类
        open fun foo() {
            println("A")
        }
    }

    class A1(name: String, age: Int, height: Float) : A("小明", 12) {
        private var name: String = name
        private var age: Int = age
        private var height: Float = height
        override fun foo() {
            println(A1(name, age, height).toString())
        }
    }

    open class B(name: String) {
        open fun foo() {
        }
    }

    class B1 : B {
        constructor(name: String, age: Int) : super(name) {

        }

        override fun foo() {
            println("B1")
        }
    }

    /**
     * 二、重写
     * 1.在基类中声明的函数默认是使用final修饰的，不能够用被子类重写，如果需要子类重写的话需要改为open关键字修饰
     * 2.如果有多个重名的方法，则必须要重写该方法，然后使用super范型去选择性的调用父类的实现
     */
    open class C {
        open fun foo() {
            println("C")
        }

        fun funC() {
            println("funC")
        }
    }

    interface D {
        fun foo() {
            println("D")
        }
    }

    class E() : D, C() {
        override fun foo() {
            super<D>.foo() //调用D().foo()
            super<C>.foo() //调用C().foo()
        }
    }

    /**
     * 三、属性重写
     * 1.属性重写使用 override 关键字，属性必须具有兼容类型，每一个声明的属性都可以通过初始化程序或者getter法被重写
     * 2.可以在在一个var属性重写一个val值，但是反过来就不行，应为val属性的值没有setter方法
     */
    open class F {
        open val name: String = ""
            get() {
                return field
            }
    }

    class F1 : F() {
        override val name: String
            get() = super.name
    }

    interface G {
        var name: String
    }

    class G1(override var name: String) : G {//第一种方法
    }

    class G2 : G {
        override var name: String = "" //第二种方法

    }


}
